package com.rickpan.service;

import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Service;

import com.rickpan.dto.response.TeamMessageDTO;
import com.rickpan.socketio.TeamEventHandler;
import com.rickpan.service.TeamMemberService;

import java.io.IOException;

/**
 * 团队消息消费者
 * 负责消费RabbitMQ队列中的团队消息并处理
 * 
 * @author 开发团队协调员
 * @since 2025-07-17
 */
@Service
@ConditionalOnProperty(name = "spring.rabbitmq.host", matchIfMissing = false)
public class TeamMessageConsumer {

    private static final Logger logger = LoggerFactory.getLogger(TeamMessageConsumer.class);

    @Autowired
    private TeamEventHandler teamEventHandler;

    @Autowired
    private TeamMemberService teamMemberService;

    // ==================== 团队消息消费 ====================

    /**
     * 消费团队消息队列（动态版本）
     * 阶段2：支持所有团队的动态队列
     *
     * @param message 消息内容
     */
    @RabbitListener(queues = "#{@messageQueueService.getAllTeamMessageQueues()}",
                   containerFactory = "rabbitListenerContainerFactory",
                   ackMode = "AUTO") // 使用自动确认
    public void handleTeamMessageDynamic(@Payload TeamMessageDTO message) {
        try {
            logger.info("📨 接收到团队消息（动态模式）: teamId={}, messageId={}, messageType={}",
                       message.getTeamId(), message.getId(), message.getMessageType());

            // 通过Socket.IO广播给团队成员
            if (teamEventHandler != null) {
                teamEventHandler.broadcastToTeam(message.getTeamId(), "new_team_message", message);
                logger.info("✅ 团队消息已通过Socket.IO广播: teamId={}, messageId={}",
                           message.getTeamId(), message.getId());
            } else {
                logger.warn("⚠️ TeamEventHandler不可用，无法广播消息");
            }

        } catch (Exception e) {
            logger.error("❌ 处理团队消息失败: teamId={}, messageId={}",
                        message.getTeamId(), message.getId(), e);
            // 抛出异常让Spring AMQP处理重试
            throw new RuntimeException("消息处理失败", e);
        }
    }

    /**
     * 消费团队消息队列（原始版本 - 暂时禁用）
     * 改为监听所有用户通知队列的模式，通过队列名称模式匹配
     * 这样可以处理所有用户的团队消息
     *
     * @param message 消息内容
     * @param channel RabbitMQ通道
     * @param deliveryTag 消息标签
     */
    // @RabbitListener(queues = "#{@messageQueueService.getAllTeamMessageQueues()}",
    //                containerFactory = "rabbitListenerContainerFactory")
    public void handleTeamMessage(@Payload TeamMessageDTO message,
                                 Channel channel,
                                 @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        
        logger.info("📥 接收到团队消息: teamId={}, messageId={}, messageType={}", 
                   message.getTeamId(), message.getId(), message.getMessageType());

        try {
            // 1. 消息验证
            if (!validateMessage(message)) {
                logger.warn("⚠️ 消息验证失败: teamId={}, messageId={}", 
                           message.getTeamId(), message.getId());
                acknowledgeMessage(channel, deliveryTag, false);
                return;
            }

            // 2. 处理消息（通过现有的TeamEventHandler）
            processTeamMessage(message);

            // 3. 确认消息处理成功
            acknowledgeMessage(channel, deliveryTag, true);
            
            logger.info("✅ 团队消息处理成功: teamId={}, messageId={}", 
                       message.getTeamId(), message.getId());

        } catch (Exception e) {
            logger.error("❌ 团队消息处理失败: teamId={}, messageId={}", 
                        message.getTeamId(), message.getId(), e);
            
            // 处理失败，拒绝消息并决定是否重新入队
            handleMessageFailure(channel, deliveryTag, message, e);
        }
    }

    /**
     * 消费用户通知队列中的团队消息
     * 暂时注释掉，因为我们现在使用Socket.IO降级方案
     *
     * @param message 消息内容
     * @param channel RabbitMQ通道
     * @param deliveryTag 消息标签
     * @param queueName 队列名称（用于识别是哪个用户的队列）
     */
    // @RabbitListener(bindings = @QueueBinding(
    //     value = @Queue(value = "user.notification.*", durable = "true"),
    //     exchange = @Exchange(value = "team.fanout", type = ExchangeTypes.FANOUT, durable = "true")
    // ), containerFactory = "rabbitListenerContainerFactory")
    public void handleUserNotificationMessage(@Payload TeamMessageDTO message,
                                            Channel channel,
                                            @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
                                            @Header("amqp_consumerQueue") String queueName) {

        logger.info("📥 用户队列接收到团队消息: queue={}, teamId={}, messageId={}",
                   queueName, message.getTeamId(), message.getId());

        try {
            // 从队列名称中提取用户ID
            String userIdStr = queueName.replace("user.notification.", "");
            Long userId = Long.valueOf(userIdStr);

            // 验证消息是否应该发送给这个用户（检查是否是团队成员）
            if (!isUserInTeam(userId, message.getTeamId())) {
                logger.debug("⚠️ 用户不在团队中，跳过消息: userId={}, teamId={}", userId, message.getTeamId());
                acknowledgeMessage(channel, deliveryTag, true);
                return;
            }

            // 处理消息（通过现有的TeamEventHandler）
            processTeamMessageForUser(message, userId);

            // 确认消息处理成功
            acknowledgeMessage(channel, deliveryTag, true);

            logger.info("✅ 用户团队消息处理成功: userId={}, teamId={}, messageId={}",
                       userId, message.getTeamId(), message.getId());

        } catch (Exception e) {
            logger.error("❌ 用户团队消息处理失败: queue={}, teamId={}, messageId={}",
                        queueName, message.getTeamId(), message.getId(), e);

            // 处理失败，拒绝消息并决定是否重新入队
            handleMessageFailure(channel, deliveryTag, message, e);
        }
    }

    /**
     * 消费文件上传进度消息
     */
    @RabbitListener(queues = "file.upload.progress")
    public void handleFileUploadProgress(@Payload Object progressMessage,
                                       Channel channel,
                                       @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        
        logger.debug("📥 接收到文件上传进度消息");

        try {
            // 处理文件上传进度
            processFileUploadProgress(progressMessage);
            
            // 确认消息
            acknowledgeMessage(channel, deliveryTag, true);
            
        } catch (Exception e) {
            logger.error("❌ 文件上传进度处理失败", e);
            acknowledgeMessage(channel, deliveryTag, false);
        }
    }

    /**
     * 消费系统广播消息
     */
    @RabbitListener(queues = "system.broadcast")
    public void handleSystemBroadcast(@Payload Object broadcastMessage,
                                    Channel channel,
                                    @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        
        logger.info("📥 接收到系统广播消息");

        try {
            // 处理系统广播
            processSystemBroadcast(broadcastMessage);
            
            // 确认消息
            acknowledgeMessage(channel, deliveryTag, true);
            
        } catch (Exception e) {
            logger.error("❌ 系统广播处理失败", e);
            acknowledgeMessage(channel, deliveryTag, false);
        }
    }

    /**
     * 消费死信队列消息
     */
    @RabbitListener(queues = "message.dlq")
    public void handleDeadLetterMessage(@Payload Object deadMessage,
                                      Channel channel,
                                      @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
                                      Message message) {
        
        logger.warn("💀 接收到死信消息: routingKey={}", message.getMessageProperties().getReceivedRoutingKey());

        try {
            // 记录死信消息
            logDeadLetterMessage(deadMessage, message);
            
            // 可以在这里实现死信消息的特殊处理逻辑
            // 例如：发送告警、记录到数据库、人工干预等
            
            // 确认死信消息
            acknowledgeMessage(channel, deliveryTag, true);
            
        } catch (Exception e) {
            logger.error("❌ 死信消息处理失败", e);
            acknowledgeMessage(channel, deliveryTag, false);
        }
    }

    // ==================== 消息处理逻辑 ====================

    /**
     * 处理团队消息
     *
     * @param message 团队消息
     */
    private void processTeamMessage(TeamMessageDTO message) {
        try {
            // 通过TeamEventHandler广播消息到Socket.IO客户端
            teamEventHandler.broadcastTeamMessageFromQueue(message);

            logger.info("📡 团队消息处理完成: teamId={}, messageId={}",
                       message.getTeamId(), message.getId());

        } catch (Exception e) {
            logger.error("❌ 团队消息处理失败: teamId={}, messageId={}",
                        message.getTeamId(), message.getId(), e);
            throw e;
        }
    }

    /**
     * 为特定用户处理团队消息
     *
     * @param message 团队消息
     * @param userId 用户ID
     */
    private void processTeamMessageForUser(TeamMessageDTO message, Long userId) {
        try {
            // 通过TeamEventHandler向特定用户发送消息
            teamEventHandler.broadcastTeamMessageToUser(message, userId);

            logger.info("📡 用户团队消息处理完成: userId={}, teamId={}, messageId={}",
                       userId, message.getTeamId(), message.getId());

        } catch (Exception e) {
            logger.error("❌ 用户团队消息处理失败: userId={}, teamId={}, messageId={}",
                        userId, message.getTeamId(), message.getId(), e);
            throw e;
        }
    }

    /**
     * 检查用户是否在团队中
     *
     * @param userId 用户ID
     * @param teamId 团队ID
     * @return 是否在团队中
     */
    private boolean isUserInTeam(Long userId, Long teamId) {
        try {
            return teamMemberService.isTeamMember(teamId, userId);
        } catch (Exception e) {
            logger.error("❌ 检查用户团队关系失败: userId={}, teamId={}", userId, teamId, e);
            return false;
        }
    }

    /**
     * 处理文件上传进度
     * 
     * @param progressMessage 进度消息
     */
    private void processFileUploadProgress(Object progressMessage) {
        // 处理文件上传进度逻辑
        // 可以通过Socket.IO推送给相关用户
        logger.debug("📊 文件上传进度处理: {}", progressMessage);
    }

    /**
     * 处理系统广播
     *
     * @param broadcastMessage 广播消息
     */
    private void processSystemBroadcast(Object broadcastMessage) {
        try {
            // 通过TeamEventHandler广播系统消息
            teamEventHandler.broadcastSystemMessageFromQueue(broadcastMessage);
            logger.info("📢 系统广播处理完成: {}", broadcastMessage);
        } catch (Exception e) {
            logger.error("❌ 系统广播处理失败: {}", broadcastMessage, e);
            throw e;
        }
    }

    // ==================== 消息验证和确认 ====================

    /**
     * 验证消息格式和内容
     * 
     * @param message 团队消息
     * @return 是否有效
     */
    private boolean validateMessage(TeamMessageDTO message) {
        if (message == null) {
            return false;
        }
        
        if (message.getTeamId() == null || message.getTeamId() <= 0) {
            return false;
        }
        
        if (message.getSenderId() == null || message.getSenderId() <= 0) {
            return false;
        }
        
        if (message.getContent() == null || message.getContent().trim().isEmpty()) {
            return false;
        }
        
        if (message.getMessageType() == null || message.getMessageType().trim().isEmpty()) {
            return false;
        }
        
        return true;
    }

    /**
     * 确认消息处理结果
     * 
     * @param channel RabbitMQ通道
     * @param deliveryTag 消息标签
     * @param success 是否成功
     */
    private void acknowledgeMessage(Channel channel, long deliveryTag, boolean success) {
        try {
            if (success) {
                channel.basicAck(deliveryTag, false);
            } else {
                channel.basicNack(deliveryTag, false, false); // 不重新入队
            }
        } catch (IOException e) {
            logger.error("❌ 消息确认失败: deliveryTag={}", deliveryTag, e);
        }
    }

    /**
     * 处理消息失败情况
     * 
     * @param channel RabbitMQ通道
     * @param deliveryTag 消息标签
     * @param message 失败的消息
     * @param exception 异常信息
     */
    private void handleMessageFailure(Channel channel, long deliveryTag, 
                                    TeamMessageDTO message, Exception exception) {
        try {
            // 获取重试次数
            int retryCount = message.getRetryCount() != null ? message.getRetryCount() : 0;
            
            if (retryCount < 3) {
                // 重试次数未超限，重新入队
                channel.basicNack(deliveryTag, false, true);
                logger.info("🔄 消息将重新入队重试: teamId={}, messageId={}, retryCount={}", 
                           message.getTeamId(), message.getId(), retryCount + 1);
            } else {
                // 重试次数超限，拒绝消息（进入死信队列）
                channel.basicNack(deliveryTag, false, false);
                logger.error("💀 消息重试次数超限，进入死信队列: teamId={}, messageId={}", 
                            message.getTeamId(), message.getId());
            }
            
        } catch (IOException e) {
            logger.error("❌ 消息失败处理异常: deliveryTag={}", deliveryTag, e);
        }
    }

    /**
     * 记录死信消息
     * 
     * @param deadMessage 死信消息内容
     * @param message 消息属性
     */
    private void logDeadLetterMessage(Object deadMessage, Message message) {
        logger.error("💀 死信消息详情: " +
                    "routingKey={}, " +
                    "exchange={}, " +
                    "content={}", 
                    message.getMessageProperties().getReceivedRoutingKey(),
                    message.getMessageProperties().getReceivedExchange(),
                    deadMessage);
        
        // 这里可以添加更多的死信处理逻辑
        // 例如：发送告警邮件、记录到监控系统等
    }
}
